package cn.virens.cmpt.rabbit;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.ShutdownSignalException;

import cn.virens.cmpt.rabbit.packet.PacketReply;
import cn.virens.common.MapUtil;
import cn.virens.common.StringUtil;
import cn.virens.exception.ExceptionUtil;

public class RabbitConsumer implements Consumer {
	private final Charset charset = Charset.forName("UTF-8");

	private final RabbitManagerImpl rabbitManager;

	protected RabbitConsumer(RabbitManagerImpl rabbitManager) {
		this.rabbitManager = rabbitManager;
	}

	@Override
	public void handleConsumeOk(String consumerTag) {

	}

	@Override
	public void handleCancelOk(String consumerTag) {

	}

	@Override
	public void handleCancel(String consumerTag) throws IOException {

	}

	@Override
	public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] bytes) throws IOException {
		RabbitConsumerProps props = new RabbitConsumerProps();

		props.setReply(MapUtil.getBoolean(properties.getHeaders(), RabbitHeaders.REPLY));
		props.setCmd(MapUtil.getString(properties.getHeaders(), RabbitHeaders.CMD));
		props.setMac(MapUtil.getString(properties.getHeaders(), RabbitHeaders.MAC));

		props.setProperties(Objects.requireNonNull(properties));
		props.setEnvelope(Objects.requireNonNull(envelope));

		try {
			String command = props.getCmd();
			String body = StringUtil.str(bytes, charset);

			// 遍历可用数据处理单元，如果能处理就进行处理
			for (RabbitConsumerHandler<?> handler : rabbitManager.mHandlers) {
				if (handler.isSupport(command) && handler.doHandler(props, body)) {
					rabbitManager.mChannel.basicAck(props.getDeliveryTag(), false);

					return;
				}
			}

			rabbitManager.mChannel.basicReject(props.getDeliveryTag(), false);
		} catch (Exception e) {
			if (props.getReply() != null && props.getReply()) {
				PacketReply packetReply = new PacketReply();
				packetReply.setRabbitRoutingKey(rabbitManager.routingKey);
				packetReply.setRabbitExchange(rabbitManager.exchange);
				packetReply.setMessage(ExceptionUtil.getMessage(e));
				packetReply.setCode(ExceptionUtil.getCode(e));

				rabbitManager.sendReply(props, packetReply);
			}

			rabbitManager.mChannel.basicReject(props.getDeliveryTag(), false);
		}
	}

	@Override
	public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) {

	}

	@Override
	public void handleRecoverOk(String consumerTag) {

	}
}
